package com.pangu.task;

import com.pangu.AMApplication;
import com.pangu.service.IService;
import com.pangu.task.mark.ATaskMark;
import com.pangu.tracker.AInvokeTracker;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 一个任务的封装，支持异步或者同步执行任务 ,同步执行时 调用者必须自己获得AsyncOperation并调用get()方法 等待执行结果的返回。
 * <p/>
 * Created by cxlin
 */
public abstract class AServiceWrapper {

    public static final String TAG = AServiceWrapper.class.getSimpleName();

    protected AMApplication imContext;
    // 实际的服务
    protected IService service;
    // 执行任务的方法缓存
    protected Map<String, Method> methodMap = new HashMap<String, Method>();

    public AServiceWrapper(AMApplication imContext, IService service) {
        this.imContext = imContext;
        this.service = service;
    }

    /**
     * 表示我要强制接管某个任务 2010-7-12
     *
     * @param receiver 新的接管者
     * @param taskMark 尝试需要接管的任务
     * @author ckcs
     */
    public static AsyncOperation forceTakeoverTask(IResultReceiver receiver, ATaskMark taskMark) {
        AsyncOperation operation = takeoverExistTask(receiver, taskMark);
        return operation;
    }

    /**
     * view强制放弃接受一个任务，但数据仍被提取接收<br>
     *
     * @param taskMark 任务标示
     * @return
     */
    public static AsyncOperation forceDiscardReceiveTask(ATaskMark taskMark) {
        AsyncOperation asyncOperation = AsyncOperation.getTaskByMark(taskMark);
        if (asyncOperation != null) {
            AInvokeTracker mInvokeTracker = asyncOperation.getInvokeTracker();
            if (mInvokeTracker != null) {
                mInvokeTracker.setResultReceiver(null);
            }
        } else {
        }

        return asyncOperation;
    }

    /**
     * 强制取消所有管理的接受
     *
     * @param receiver 希望解除接受的接收器
     */
    public static void forceReleaseReceive(IResultReceiver receiver) {
        List<AsyncOperation> ops = new ArrayList<AsyncOperation>(AsyncOperation.asyncOperations());
        AsyncOperation asyncOperation = null;
        AInvokeTracker tracker = null;
        for (int index = 0; index < ops.size(); index++) {
            asyncOperation = ops.get(index);
            tracker = asyncOperation.getInvokeTracker();
            if (tracker != null && tracker.getResultReceiver() == receiver) {
                tracker.setResultReceiver(null);
            }
        }
    }

    /**
     * 检查是否任务已经存在，
     *
     * @param taskMark 任务标示
     * @return
     */
    public static boolean isTaskExist(ATaskMark taskMark) {
        return AsyncOperation.isTaskExist(taskMark);
    }

    /**
     * 直接执行一个方法
     *
     * @param methodName
     * @param args
     * @return
     * @throws Exception
     */
    protected Object executeOperation(String methodName, final Object... args) throws Exception {
        Method method = getMethod(methodName);

        return method.invoke(service, args);
    }

    /**
     * 封装一个操作
     *
     * @param invokeTracker
     * @param taskMark
     * @param methodName
     * @param attach
     * @return
     */
    protected AsyncOperation wraperOperation(AInvokeTracker invokeTracker, ATaskMark taskMark, String methodName,
                                             Object attach) {
        Method method = getMethod(methodName);
        AsyncOperation operation = new AsyncOperation(taskMark, method);
        operation.setInvokeTracker(invokeTracker);
        operation.setAttach(attach);
        return operation;
    }

    /**
     * 获得方法，如果缓存中没有这查找
     *
     * @param name
     * @return
     */
    private Method getMethod(String name) {
        Method method = methodMap.get(name);
        if (method == null) {
            Method[] methods = service.getClass().getMethods();
            for (Method aMethod : methods) {
                if (aMethod.getName().equals(name)) {
                    method = aMethod;
                    methodMap.put(name, method);
                    break;
                }
            }
        }
        if (method == null) {
            throw new NoSuchMethodError("unknow method : " + name);

        } else {
            return method;
        }
    }

    /**
     * 停止某个操作
     *
     * @param taskMark
     */
    protected static void stopAsyncOperate(ATaskMark taskMark) {
        AsyncOperation operation = AsyncOperation.getTaskByMark(taskMark);
        if (operation != null) {
            operation.clearAsysnTask(true);
        }

    }

    /**
     * 如果一个任务之前已经执行，当还没有返回的时候，如果这个时候 有新的任务请求进来，<br>
     * 那么请求者将接管此任务, 但不能更改旧任务的状态，以便保证任务的完整性。
     *
     * @param resultReceiver
     * @param taskMark
     * @return
     */
    protected static AsyncOperation takeoverExistTask(IResultReceiver resultReceiver, ATaskMark taskMark) {
        AsyncOperation asyncOperation = AsyncOperation.getTaskByMark(taskMark);
        if (asyncOperation != null) {
            AInvokeTracker mInvokeTracker = asyncOperation.getInvokeTracker();
            if (mInvokeTracker != null && mInvokeTracker.getResultReceiver() != resultReceiver) {
                mInvokeTracker.setResultReceiver(resultReceiver);
            }

        } else {
        }

        return asyncOperation;
    }

    /**
     * 关闭所有连接
     */
    public void shutdownHttpConnect() {
        // 需要关闭所有的http连接。
    }
}
